﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using mesoBoard.Data;
using mesoBoard.Data.Repositories;
using System.Drawing.Imaging;
using System.Drawing;
using mesoBoard.Common;

namespace mesoBoard.Services
{
    public class Threads : IThreads
    {
        private IRepositoriesWrapper Repositories;

        public Threads(IRepositoriesWrapper repos)
        {
            this.Repositories = repos;
        }

        public Thread GetThread(int threadID)
        {
            return Repositories.Threads.GetThread(threadID);
        }

        public IEnumerable<Thread> GetGlobalAnnouncements()
        {
            return Repositories.Threads.GetGlobalAnnouncements();
        }

        public void CreateThread(Thread thread, Post firstPost, string pollText, string pollOptions)
        {
            Repositories.Threads.CreateThread(thread, firstPost, pollText, pollOptions.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
        }

        public void CreateThread(Thread thread, Post firstPost)
        {
            Repositories.Threads.CreateThread(thread, firstPost);
        }

        public void UpdateThread(Thread theThread, Post thePost, HttpFileCollectionBase files)
        {
            Posts postServices = new Posts(this.Repositories);
            postServices.UpdatePost(thePost, files);

            Repositories.Threads.UpdateThread(theThread);
            Repositories.Forums.SyncForum(theThread.ForumID);
            Repositories.Threads.SyncThread(theThread.ThreadID);
        }

        public void ThreadViewed(int threadID, int userID)
        {
            Repositories.Threads.DeleteThreadViewStamp(userID, threadID);
            Repositories.Threads.AddViewed(threadID, userID);
            Repositories.Threads.AddThreadView(threadID, userID);
        }

        public Thread CreateThread(
            int forumID,
            int userID,
            int threadType,
            string threadImage,
            Post firstPost,
            string pollText,
            string[] pollOptions,
            HttpFileCollectionBase files)
        {
            Thread theThread = new Thread
            {
                ForumID = forumID,
                Type = threadType,
                Views = 0,
                Image = threadImage,
            };

            Repositories.Threads.CreateThread(theThread);

            firstPost.UserID = int.Parse(HttpContext.Current.User.Identity.Name);
            firstPost.Date = DateTime.UtcNow;
            firstPost.ThreadID = theThread.ThreadID;

            Repositories.Posts.CreatePost(firstPost);

            theThread.FirstPostID = firstPost.PostID;
            theThread.LastPostID = firstPost.PostID;
            theThread.HasPoll = false;
            theThread.HasAttachment = false;
            theThread.TotalPosts = 0;

            if (!string.IsNullOrWhiteSpace(pollText))
            {
                System.Data.Objects.DataClasses.EntityCollection<PollOption> options = new System.Data.Objects.DataClasses.EntityCollection<PollOption>();
                foreach (string po in pollOptions)
                {
                    options.Add(new PollOption
                    {
                        PollID = theThread.ThreadID,
                        Text = po
                    });
                }

                Poll thePoll = new Poll
                {
                    PollOptions = options,
                    Question = pollText,
                    PollID = theThread.ThreadID
                };
                theThread.HasPoll = true;
                Repositories.Polls.CreatePoll(thePoll);
            }

            if (files.Count != 0)
            {
                Files filesServices = new Files(this.Repositories);
                filesServices.CreateAttachments(files, firstPost.PostID);
                theThread.HasAttachment = true;
            }

            Repositories.Threads.UpdateThread(theThread);
            Repositories.Forums.SyncForum(forumID);
            Repositories.Users.SyncUser(userID);
            return theThread;
        }

        public string Subscribe(int threadID, int userID)
        {
            string authCode = Randoms.CleanGUID();

            Repositories.Threads.CreateSubscription(new Subscription
            {
                ThreadID = threadID,
                UserID = userID,
                AuthenticationCode = authCode
            });

            return authCode;
        }

        public IEnumerable<Post> GetPosts(int threadID)
        {
            return Repositories.Posts.GetPosts(threadID);
        }

        public void Unsubscribe(int threadID, int userID)
        {
            Repositories.Threads.DeleteSubscription(userID, threadID);
        }

        public void Lock(int threadID)
        {
            Thread thread = Repositories.Threads.GetThread(threadID);
            thread.IsLocked = true;
            Repositories.Threads.UpdateThread(thread);
        }

        public void Unlock(int threadID)
        {
            Thread thread = Repositories.Threads.GetThread(threadID);
            thread.IsLocked = false;
            Repositories.Threads.UpdateThread(thread);
        }


        public IEnumerable<Thread> GetPagedThreads(int forumID, int pageNumber, int pageSize, OrderBy orderBy = OrderBy.Date, Direction direction = Direction.Descending)
        {
            IEnumerable<Thread> forumThreads = Repositories.Threads.GetThreads(forumID);

            switch (orderBy)
            {
                default:
                    forumThreads = forumThreads.OrderByDescending(x => x.LastPost.Date).OrderByDescending(x => x.Type);
                    break;
            }

            if (direction == Direction.Ascending)
                forumThreads.Reverse();

            forumThreads = forumThreads.Skip((pageNumber - 1) * pageSize).Take(pageSize);

            return forumThreads;
        }

        public bool HasNewPost(int threadID, int userID)
        {
            Thread TheThread = GetThread(threadID);

            Post LastPost = Repositories.Posts.GetPost(TheThread.LastPostID);

            User TheUser = Repositories.Users.GetUser(userID);

            if (TheUser == null || TheUser.UserID == 0)
                return false;

            if (LastPost.UserID == userID)
                return false;

            ThreadViewStamp FoundView = Repositories.Threads.GetThreadViewStamp(userID, threadID);

            if (FoundView != null)
                return DateTime.Compare(LastPost.Date, FoundView.Date) > 0;
            else
                return DateTime.Compare(LastPost.Date, TheUser.LastLogoutDate) > 0;

        }

        public bool CanLock(User theUser)
        {
            if (theUser == null)
                return false;

            if (theUser.IsInRole("Moderator") || theUser.IsInRole("Admin"))
                return true;
            else
                return false;
        }

        public bool HasVoted(int threadID, int userID)
        {
            if (userID == 0)
                return true;

            Polls polls = new Polls(this.Repositories);

            // threadID is used because polls has a one-to-one mapping with thread
            return polls.HasVoted(threadID, userID);
        }

        public bool IsSubscribed(int threadID, int userID)
        {
            if (userID == 0)
                return false;
            IEnumerable<Subscription> subscriptions = Repositories.Threads.GetSubscriptions(threadID);

            return subscriptions.FirstOrDefault(x => x.ThreadID == threadID && x.UserID == userID) != null;

            
        }
    }
}